package xin.alum.aim.groups;

import io.netty.channel.Channel;
import org.springframework.stereotype.Component;
import xin.alum.aim.model.Transportable;
import xin.alum.aim.util.ApplicationContextUtil;

import java.util.concurrent.ConcurrentHashMap;

/**
 * 群组Sesions 管理通道
 *
 * @auther alum(alum @ live.cn)
 * @date 2021/8/3 14:29
 */
@Component
public class SessionGroups extends ConcurrentHashMap<String, Sessions> {

    /**
     * 集群配置
     */
    private final ClusterProperties clusterProperties;

    public SessionGroups(ClusterProperties clusterProperties) {
        this.clusterProperties = clusterProperties;
    }


    /**
     * 将用户连接绑定到群组
     *
     * @param ch  通道
     * @param key 组键值
     */
    public Sessions bind(Channel ch, String key) {
        Sessions nSessions = get(key);
        if (nSessions.add(ch)) {
            super.putIfAbsent(key, nSessions);
        }
        return nSessions;
    }

    /**
     * 解绑群组连接
     *
     * @param ch
     * @param key
     * @return
     */
    public void unbind(Channel ch, String key) {
        Sessions group = get(key);
        group.remove(ch);
        if (group.size() == 0) {
            super.remove(key);
        }
    }

    /**
     * 用户退出群组
     *
     * @param userId
     * @return
     */
    public Sessions exit(String userId, String key) {
        Sessions users = get(Sessions.PREFIX_BIND_USER_GROUP.concat(userId));
        Sessions group = get(key);
        users.forEach(c -> {
            group.remove(c);
        });
        return group;
    }

    /**
     * 获取群组Sessions
     *
     * @param key
     * @return
     */
    public Sessions get(String key) {
        return super.getOrDefault(key, new Sessions(key));
    }

    /**
     * 向集群指定群组推送通知
     *
     * @param groupKey
     * @param msg
     */
    public void sends(String groupKey, Transportable msg) {
        if (clusterProperties.getMode() != ClusterProperties.ClusterMode.None) {
            ApplicationContextUtil.getBean(ClusterFactory.class).push(groupKey, msg);
        } else {
            get(groupKey).sends(msg);
        }
    }
}
